package com.bingxue.edu.management.system.service;

import cn.hutool.core.bean.BeanUtil;
import com.bingxue.edu.common.enums.CommonStatusEnum;
import com.bingxue.edu.framework.common.model.LabelValue;
import com.bingxue.edu.framework.common.util.ValidationUtils;
import com.bingxue.edu.framework.mybatis.base.BaseService;
import com.bingxue.edu.management.system.mapper.DictItemMapper;
import com.bingxue.edu.management.system.mapper.DictMapper;
import com.bingxue.edu.management.system.model.entity.Dict;
import com.bingxue.edu.management.system.model.entity.DictItem;
import com.bingxue.edu.management.system.model.req.DictItemCreateReq;
import com.bingxue.edu.management.system.model.req.DictItemSortReq;
import com.bingxue.edu.management.system.model.req.DictItemUpdateReq;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.bingxue.edu.management.system.model.entity.table.DictItemTableDef.DICT_ITEM;


/**
 * 字典项业务实现
 *
 * @author xunuo
 * @since 2024/07/23 10:41
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DictItemService extends BaseService<DictItemMapper, DictItem> {

    private final   DictItemMapper dictItemMapper;
    private final   DictMapper dictMapper;

    /**
     * 根据链式查询，查询dictId
     *
     * @param ids {List<String>}
     * @return List <String>
     */
    public List<String> getDictIdsByIds(List<String> ids) {
        return this.queryChain().select(DICT_ITEM.DICT_ID).where(DICT_ITEM.ID.in(ids)).listAs(String.class);
    }

    /**
     * 新增字典项
     *
     * @param dictItemCreateReq {DictItemCreateReq}
     * @return boolean
     */
    public boolean addDictItem(DictItemCreateReq dictItemCreateReq) {
        String label = dictItemCreateReq.getLabel();
        String did = dictItemCreateReq.getDictId();
        String value = dictItemCreateReq.getValue();
        //判断字典id为did且标签为label的数据是否已经存在，如存在则抛出BusinessException异常
        ValidationUtils.throwIf(this.isLabelExist(label, null, did), "新增失败，[{}]已存在", label);
        //判断字典id为did且值为value的数据是否已经存在，如存在则抛出BusinessException异常
        ValidationUtils.throwIf(this.isValueExist(value, null, did), "新增失败，[{}]已存在", value);
        DictItem dictItem = BeanUtil.copyProperties(dictItemCreateReq, DictItem.class);
        return this.save(dictItem);
    }

    /**
     * 更新字典项
     *
     * @param dictItemCreateReq {DictItemUpdateReq}
     * @param id                {String}
     */
    public void updateDictItem(DictItemUpdateReq dictItemCreateReq, String id) {
        DictItem oldDictItem = super.getById(id);
        String label = dictItemCreateReq.getLabel();
        String did = dictItemCreateReq.getDictId();
        //当标签需要更新时，判断更新标签所在字典中是否已存在待更新的标签，如存在则抛出BusinessException异常
        ValidationUtils.throwIfNull(oldDictItem, "该字典项不存在");
        if (!oldDictItem.getLabel().equals(label)) {
            ValidationUtils.throwIf(this.isLabelExist(label, null, did), "修改失败，[{}]已存在", label);
        }
        //判断待更新的值与原来的值是否相同，不同则抛出BusinessException异常
//        ValidationUtils.throwIfNotEqual(dictItemCreateReq.getValue(), oldDictItem.getValue(), "不允许修改字典项编码");
        DictItem dictItem = BeanUtil.copyProperties(dictItemCreateReq, DictItem.class);
        dictItem.setId(id);
        this.updateById(dictItem);
    }



    /**
     * 删除字典项
     *
     * @param ids {List<String>}
     */
    public void deleteDictItem(List<String> ids) {
        List<String> dictIds = this.getDictIdsByIds(ids);
        List<Dict> list = dictMapper.selectListByIds(dictIds);
        ValidationUtils.throwIfEmpty(list, "所选字典[%s]不存在", dictIds.get(0));
        Dict firstSystemDict = list.get(0);
        ValidationUtils.throwIf(firstSystemDict.getReserved(), "所选字典[{}]是系统内置字典，不允许删除", firstSystemDict.getName());
        this.removeByIds(ids);
    }

    /**
     * 判断该标签是否已存在
     *
     * @param label {String}
     * @param id    {String}
     * @param did   {String}
     * @return {boolean}
     */
    public boolean isLabelExist(String label, String id, String did) {
        return this.queryChain().where(DICT_ITEM.LABEL.eq(label)).and(DICT_ITEM.DICT_ID.eq(did)).and(DICT_ITEM.ID.eq(id)).exists();
    }

    /**
     * 判断编码是否存在
     *
     * @param value {String}
     * @param id    {String}
     * @param did   {String}
     * @return {boolean}
     */
    public boolean isValueExist(String value, String id, String did) {
        return this.queryChain().where(DICT_ITEM.VALUE.eq(value)).and(DICT_ITEM.DICT_ID.eq(did)).and(DICT_ITEM.ID.eq(id)).exists();
    }

    /**
     * 排序字典项
     * @param req 排序请求
     */
    @Transactional(rollbackFor = Exception.class)
    public void sortDictItems(DictItemSortReq req) {
        int sort = 1;
        for (String dictItemId : req.getDictItemIds()) {
            this.updateChain().where(DICT_ITEM.ID.eq(dictItemId)).set(DICT_ITEM.SORT, sort).update();
            sort ++;
        }
    }

    /**
     * 查询所有字典数据map
     */
    @SuppressWarnings("rawtypes")
    public Map<String, List<LabelValue>> listDictMap() {
        List<Dict> dictList = dictMapper.selectAll();
        Map<String, List<LabelValue>> listMap = dictList.stream().collect(Collectors.toMap(Dict::getId, s -> new LinkedList<>()));

        QueryWrapper queryWrapper = QueryWrapper.create().where(DICT_ITEM.STATUS.eq(CommonStatusEnum.ENABLED));
        List<DictItem> dictItemList = this.list(queryWrapper);
        for (DictItem dictItem : dictItemList) {
            List<LabelValue> labelValueList = listMap.get(dictItem.getDictId());
            if (labelValueList != null) {
                LabelValue<String> labelValue = new LabelValue<>(dictItem.getLabel(), dictItem.getValue());
                labelValue.put("color", dictItem.getColor());
                labelValueList.add(labelValue);
            }
        }
        for (Dict dict : dictList) {
            listMap.put(dict.getCode(), listMap.remove(dict.getId()));
        }
        return listMap;
    }

    /**
     * 根据DictItem的Label找value
     * @param label
     * @param dictId
     * @return
     */
    public String getDictItemValueByLabel(String label, String dictId){

        return this.getOneAs(QueryWrapper.create()
                .select(DICT_ITEM.VALUE)
                .where(DICT_ITEM.DICT_ID.eq(dictId))
                        .and(DICT_ITEM.LABEL.eq(label))
                ,String.class);
    }
}
